<template>
  <section class="fav-list-container">
    <h2>{{ title }}</h2>
    <div infinite-wrapper v-on:scroll="onScroll">
      <div v-if="category === 'media'">
        <div
          v-for="group in groupedMediaItems"
          :key="group.category"
          class="media-category-container"
        >
          <p>{{ group.category }}</p>
          <ul class="media-category-items">
            <li
              v-for="(favItem, index) in group.items"
              @contextmenu="openFavContextMenu($event, favItem)"
              @click="handleClickMedia(index, group.items)"
              :key="favItem.id"
            >
              <div v-if="favItem.type === 3" class="media-item-image">
                <img :src="favItem.url" />
              </div>
              <div v-else class="media-item-video">
                <video preload="metadata" :src="favItem.url" />
                <i class="icon-ion-play"></i>
              </div>
            </li>
          </ul>
        </div>
      </div>
      <ul v-else>
        <li
          v-for="(favItem, index) in filteredFavItems"
          @contextmenu="openFavContextMenu($event, favItem)"
          :key="index"
        >
          <div class="fav-item-container" @click="handleClick(favItem)">
            <div class="fav-item-content">
              <!--            文件-->
              <div v-if="favItem.type === 5" class="fav-item-file">
                <img
                  :src="
                    require(`@/assets/images/filetypes/${favItem._fileIconName}`)
                  "
                  alt=""
                />
                <div class="name-size">
                  <p class="name">{{ favItem.title }}</p>
                  <p class="size">{{ favItem._sizeStr }}</p>
                </div>
              </div>
              <!--            图片-->
              <div v-else-if="favItem.type === 3" class="fav-item-image">
                <img :src="favItem.url" />
              </div>
              <!--            视频-->
              <div v-else-if="favItem.type === 6" class="fav-item-video">
                <video preload="metadata" :src="favItem.url" />
                <i class="icon-ion-play"></i>
              </div>
              <!--            语音消息-->
              <div v-else-if="favItem.type === 2" class="fav-item-audio">
                <audio preload="auto" controls controlsList="nodownload">
                  <source
                    :src="appServerAudioUrl(favItem.url)"
                    type="audio/mp4"
                  />
                </audio>
              </div>
              <!--                            组合消息-->
              <div v-else-if="favItem.type === 11" class="fav-item-other">
                <p>
                  {{ favItem._content }}
                </p>
              </div>
              <!--            其他-->
              <div v-else class="fav-item-other">
                <p>
                  {{ favItem.title }}
                </p>
              </div>
            </div>
            <div class="fav-item-sender-time">
              <p class="time">{{ favItem._timeStr }}</p>
              <p class="sender">{{ $t('fav.from') + ': ' + favItem.origin }}</p>
            </div>
          </div>
        </li>
      </ul>
      <infinite-loading
        :identifier="infiniteId"
        force-use-infinite-wrapper
        direction="bottom"
        @infinite="infiniteHandler"
      >
        <!--            <template slot="spinner">加载中...</template>-->
        <template #no-more>{{ $t('fav.no_more') }}</template>
        <template #no-results>{{ $t('fav.all_fav_load') }}</template>
      </infinite-loading>
      <vue-context
        ref="menu"
        v-slot="{ data: favItem }"
        :close-on-scroll="true"
        v-on:close="onMenuClose"
      >
        <!--          更多menu item-->
        <li>
          <a @click.prevent="deleteFav(favItem)">{{ $t('common.delete') }}</a>
        </li>
        <li>
          <a @click.prevent="forward(favItem)">{{
            $t('misc.send_to_friend')
          }}</a>
        </li>
      </vue-context>
    </div>
  </section>
</template>

<script>
import helper from '../../util/helper'
import MessageContentType from '../../../wfc/messages/messageContentType'
import wfc from '../../../wfc/client/wfc'
import InfiniteLoading from '@imndx/vue-infinite-loading'
import store from '../../../store'
import { ipcRenderer } from '../../../platform'
import FavItem from '../../../wfc/model/favItem'
import { isElectron } from '../../../platform'
import { _reverseToJsLongString } from '../../../wfc/util/longUtil'
import CompositeMessageContent from '../../../wfc/messages/compositeMessageContent'
import Config from '../../../config'
import IpcEventType from '../../../ipcEventType'
import appServerApi from '../../../api/appServerApi'
import { downloadFile } from '../../../platformHelper'

export default {
  name: 'FavListView',
  props: {
    category: {
      type: String,
      default: 'all',
      required: false,
    },
  },
  data() {
    return {
      favItems: [],
      imagePlaceHolder:
        'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNcunDhfwAGwgLoe4t2fwAAAABJRU5ErkJggg==',
      infiniteId: +new Date(),
    }
  },
  methods: {
    /**
     *
     * @param category
     * @param cb {function(number, boolean, boolean)}}
     * @return {Promise<void>}
     */
    async loadFavList(category, cb) {
      let startId =
        this.favItems.length > 0
          ? this.favItems[this.favItems.length - 1].id
          : 0
      let responseData = await appServerApi.getFavList(startId, 20)
      let data = _reverseToJsLongString(responseData, 'messageUid')
      data = JSON.parse(data)
      if (data && data.result) {
        let obj = data.result
        let items = obj.items
        let found = false
        for (let i = 0; i < items.length; i++) {
          if (category === 'all') {
            found = true
            break
          }
          if (
            category === 'file' &&
            items[i].type === MessageContentType.File
          ) {
            found = true
            break
          }
          if (
            category === 'media' &&
            [MessageContentType.Image, MessageContentType.Video].indexOf(
              items[i].type
            ) >= 0
          ) {
            found = true
            break
          }
          if (
            category === 'composite' &&
            items[i].type === MessageContentType.Composite_Message
          ) {
            found = true
            break
          }
        }
        this._patchFavItem(items)
        this.favItems = this.favItems.concat(items)
        if (obj.hasMore && !found && cb) {
          this.loadFavList(category, cb)
          return
        }
        cb && cb(obj.hasMore)
      } else {
        console.error('loadFavList failed', responseData)
        cb && cb(false)
      }
    },

    _patchFavItem(favItems) {
      favItems.forEach((fi) => {
        if (fi.data) {
          if (fi.type === MessageContentType.Composite_Message) {
            let favItem = Object.assign(new FavItem(), fi)
            favItem.favType = fi.type
            let message = favItem.toMessage()
            let compositeContent = message.messageContent
            fi._content = fi.title
            if (compositeContent instanceof CompositeMessageContent) {
              for (
                let i = 0;
                i < compositeContent.messages.length && i < 2;
                i++
              ) {
                fi._content += '\n'
                fi._content += compositeContent.messages[
                  i
                ].messageContent.digest(compositeContent.messages[i])
              }
            }
            message.messageContent = compositeContent

            fi._message = message
          } else {
            fi.data = JSON.parse(fi.data)
          }
        }
        fi._timeStr = helper.dateFormat(fi.timestamp)
        if (fi.type === MessageContentType.File) {
          fi.title = fi.title ? fi.title : 'unname'
          fi._fileIconName = helper.getFiletypeIcon(
            fi.title.substring(fi.title.lastIndexOf('.'))
          )
          fi._sizeStr = helper.humanSize(fi.data.size)
        }
        fi._senderName = wfc.getUserDisplayName(fi.sender)
      })
    },

    infiniteHandler($state) {
      this.loadFavList(this.category, (hasMore) => {
        if (hasMore) {
          $state.loaded()
        } else {
          $state.complete()
        }
      })
    },
    handleClick(favItem) {
      switch (favItem.type) {
        case MessageContentType.Text:
          if (isElectron()) {
            let hash = window.location.hash
            let url = window.location.origin
            if (hash) {
              url = window.location.href.replace(hash, '#/message')
            } else {
              url += '/message'
            }
            url +=
              '?data=' + wfc.escape(wfc.utf8_to_b64(JSON.stringify(favItem)))
            ipcRenderer.send(IpcEventType.SHOW_COMPOSITE_MESSAGE_WINDOW, {
              url: url,
            })
          } else {
            this.$notify({
              text: '暂不支持预览，请手机端或者 PC 端查看',
              type: 'info',
            })
          }
          break
        case MessageContentType.Image:
        case MessageContentType.Video:
          store.previewMedia(
            favItem.url,
            favItem.thumbUrl,
            favItem.data && favItem.data.thumb
              ? favItem.data.thumb
              : 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNcunDhfwAGwgLoe4t2fwAAAABJRU5ErkJggg=='
          )
          break
        case MessageContentType.File:
          let fi = Object.assign(new FavItem(), favItem)
          downloadFile(fi.toMessage())
          break
        case MessageContentType.Composite_Message:
          if (isElectron()) {
            let hash = window.location.hash
            let url = window.location.origin
            if (hash) {
              url = window.location.href.replace(hash, '#/composite')
            } else {
              url += '/composite'
            }
            url +=
              '?data=' + wfc.escape(wfc.utf8_to_b64(JSON.stringify(favItem)))
            ipcRenderer.send(IpcEventType.SHOW_COMPOSITE_MESSAGE_WINDOW, {
              url: url,
            })
          } else {
            this.$notify({
              text: '暂不支持预览，请手机端或者 PC 端查看',
              type: 'info',
            })
          }
          break
        default:
          console.log('todo click', favItem)
          break
      }
    },
    handleClickMedia(index, favItems) {
      let mediaItems = []
      favItems = favItems.filter(
        (favItem) =>
          favItem.url ||
          favItem.thumbUrl ||
          (favItem.data && favItem.data.thumb)
      )
      favItems.forEach((favItem) => {
        let thumb = favItem.thumbUrl
          ? favItem.thumbUrl
          : favItem.data && favItem.data.thumb
          ? 'data:image/png;base64,' + favItem.data.thumb
          : ''
        mediaItems.push({
          src: favItem.url,
          thumb: thumb,
          autoplay: true,
        })
      })
      store.previewMedias(mediaItems, index)
    },
    openFavContextMenu(event, favItem) {
      if (!favItem) {
        return
      }
      if (
        favItem.type ===
        MessageContentType.MESSAGE_CONTENT_TYPE_MIX_MULTI_MEDIA_TEXT
      ) {
        this.$notify({
          text: '此类型，暂不支持转发',
          type: 'warn',
        })
        return
      }
      this.$refs.menu.open(event, favItem)
    },
    onMenuClose() {
      // do nothing
    },

    deleteFav(favItem) {
      appServerApi
        .delFav(favItem.id)
        .then((response) => {
          this.favItems = this.favItems.filter((fi) => fi.id !== favItem.id)
        })
        .catch((err) => {
          console.log('delFav error', err)
        })
    },

    forward(favItem) {
      favItem = Object.assign(new FavItem(), favItem)
      favItem.favType = favItem.type
      this.$eventBus.$emit('forward-fav', {
        favItem: favItem,
      })
    },
    onScroll() {
      // hide message context menu
      this.$refs.menu && this.$refs.menu.close()
    },

    appServerAudioUrl(url) {
      return Config.AMR_TO_MP3_SERVER_ADDRESS + url
    },
  },

  computed: {
    title() {
      let str = this.$t('fav.fav')
      switch (this.category) {
        case 'all':
          str = this.$t('fav.all')
          break
        case 'file':
          str = this.$t('fav.file')
          break
        case 'media':
          str = this.$t('fav.media')
          break
        case 'composite':
          str = this.$t('fav.composite')
          break
        default:
          break
      }
      return str
    },
    filteredFavItems() {
      let items = this.favItems
      switch (this.category) {
        case 'all':
          items = this.favItems
          break
        case 'file':
          items = this.favItems.filter(
            (fi) => fi.type === MessageContentType.File
          )
          break
        case 'media':
          items = this.favItems.filter(
            (fi) =>
              fi.type === MessageContentType.Image ||
              fi.type === MessageContentType.Video
          )
          break
        case 'composite':
          items = this.favItems.filter(
            (fi) => fi.type === MessageContentType.Composite_Message
          )
          break
        default:
          break
      }
      return items
    },

    groupedMediaItems() {
      let items = this.favItems.filter(
        (fi) =>
          fi.type === MessageContentType.Image ||
          fi.type === MessageContentType.Video
      )
      let groupedItems = []

      let months = [
        this.$t('common.month_1'),
        this.$t('common.month_2'),
        this.$t('common.month_3'),
        this.$t('common.month_4'),
        this.$t('common.month_5'),
        this.$t('common.month_6'),
        this.$t('common.month_7'),
        this.$t('common.month_8'),
        this.$t('common.month_9'),
        this.$t('common.month_10'),
        this.$t('common.month_11'),
        this.$t('common.month_12'),
      ]

      let map = new Map()
      items.forEach((item) => {
        let favDate = new Date(item.timestamp)
        let category = months[favDate.getMonth()] + ' ' + favDate.getFullYear()
        if (!map.has(category)) {
          map.set(category, [item])
        } else {
          map.get(category).push(item)
        }
      })
      groupedItems = Array.from(map).map(([category, items]) => ({
        category: category,
        items: items,
      }))

      console.log('groupedItems', groupedItems)
      // groupedItems = groupedItems.concat(groupedItems)
      return groupedItems
    },
  },

  mounted() {
    // this.loadFavList('all');
  },
  deactivated() {
    this.favItems = []
  },
  activated() {
    this.infiniteId += 1
  },
  components: {
    InfiniteLoading,
  },
}
</script>

<style lang="css" scoped>
.fav-list-container {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.fav-list-container h2 {
  width: 100%;
  height: 60px;
  font-size: 16px;
  font-style: normal;
  font-weight: normal;
  display: flex;
  align-items: center;
  padding-left: 20px;
  border-bottom: 1px solid #ebebeb;
}

.fav-list-container div {
  flex: 1;
  overflow: auto;
}

.fav-item-container {
  width: 100%;
  display: flex;
  min-height: 75px;
  max-height: 110px;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  position: relative;
  padding: 0 80px;
}

.fav-item-container:after {
  position: absolute;
  content: ' ';
  height: 0;
  left: 80px;
  right: 80px;
  bottom: 0;
  border-bottom: 1px solid #e4e4e4;
}

.fav-item-container:active {
  background-color: #dedede;
}

.fav-item-content {
  flex: 1;
  padding-right: 20px;
  display: flex;
  align-items: center;
}

.fav-item-other p {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  white-space: pre-line;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 12px;
  color: #252525;
}

.fav-item-image {
  height: 110px;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.fav-item-image img {
  height: 70px;
  width: 140px;
  object-fit: cover;
}

.fav-item-file {
  display: flex;
  font-size: 12px;
  height: 110px;
  align-items: center;
}

.fav-item-file img {
  width: 60px;
  height: 60px;
  margin: 0 20px 0 10px;
}

.fav-item-file .name-size {
  padding: 25px 0;
  height: 100%;
  flex: 1;
  max-width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.fav-item-file .name {
  color: #252525;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
}

.fav-item-file .size {
  color: #b2b2b2;
}

.fav-item-video {
  height: 110px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  position: relative;
}

.fav-item-video video {
  background-color: lightgrey;
  height: 70px;
  width: 140px;
  object-fit: cover;
}

.fav-item-video i {
  position: absolute;
  left: 68px;
  right: 0;
  width: 10px;
  margin-right: auto;
}

.fav-item-audio {
  margin: 0 10px;
}

.fav-item-audio audio {
  outline: none;
  filter: sepia(20%) saturate(70%) grayscale(1) contrast(99%) invert(12%);
}

.fav-item-sender-time {
  max-width: 120px;
  text-align: right;
}

.fav-item-sender-time .time {
  font-size: 12px;
  color: #b6b6b6;
}

.fav-item-sender-time .sender {
  font-size: 12px;
  color: #b2b2b2;
  padding-top: 3px;
}

.media-category-container {
  display: flex;
  flex-direction: column;
  padding: 0 80px;
}

.media-category-container p {
  font-size: 14px;
  padding: 20px 0 10px 0;
}

.media-category-items {
  width: 100%;
  display: flex;
  align-items: flex-start;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: flex-start;
}

.media-item-image img {
  width: 70px;
  height: 70px;
  object-fit: cover;
  padding: 2px;
}

.media-item-video {
  position: relative;
}

.media-item-video video {
  width: 70px;
  height: 70px;
  object-fit: cover;
  padding: 2px;
}

.media-item-video i {
  position: absolute;
  top: 32px;
  left: 32px;
  width: 10px;
  margin-right: auto;
}
</style>
